/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
 * This file constains code of cpu debug and npu code.We read data from bin file
 * and write result to file.
 */
#include "data_utils.h"
#include <chrono>
#include <sstream>
// #ifndef __CCE_KT_TEST__
#include "aclrtlaunch_matmul_custom.h"
#include "acl/acl.h"
// extern void matmul_custom_do(uint32_t coreDim, void *l2ctrl, void *stream,
//                             uint8_t *param1, uint8_t *param2, uint8_t *param3,
//                             int32_t M, int32_t N, int32_t K,
//                             int32_t L1_m, int32_t L1_k, int32_t L1_n,
//                             int32_t L2_m, int32_t L2_k, int32_t L2_n, int32_t buffer_num);
// #else
// #include "tikicpulib.h"
// extern "C" void matmul_custom(uint8_t *param1, uint8_t *param2, uint8_t *param3,
//                             int32_t M, int32_t N, int32_t K,
//                             int32_t L1_m, int32_t L1_k, int32_t L1_n,
//                             int32_t L2_m, int32_t L2_k, int32_t L2_n, int32_t buffer_num);

extern "C" void matmul_custom(uint8_t *param1, uint8_t *param2, uint8_t *param3, int32_t M, int32_t N, int32_t K);
// #endif

int32_t main(int32_t argc, char *argv[])
{
    int32_t M = int32_t(atoi(argv[1]));
    int32_t K = int32_t(atoi(argv[2]));
    int32_t N = int32_t(atoi(argv[3]));
    // int32_t L1_m = int32_t(atoi(argv[4]));
    // int32_t L1_k = int32_t(atoi(argv[5]));
    // int32_t L1_n = int32_t(atoi(argv[6]));
    // int32_t L2_m = int32_t(atoi(argv[7]));
    // int32_t L2_k = int32_t(atoi(argv[8]));
    // int32_t L2_n = int32_t(atoi(argv[9]));
    // int32_t buffer_num = int32_t(atoi(argv[10]));

    size_t param1FileSize = M * K * sizeof(uint16_t); // uint16_t represent half
    size_t param2FileSize = K * N * sizeof(uint16_t); // uint16_t represent half
    size_t param3FileSize = M * N * sizeof(float);
    uint32_t blockDim = 1;

    CHECK_ACL(aclInit(nullptr));
    aclrtContext context;
    int32_t deviceId = 5;
    CHECK_ACL(aclrtSetDevice(deviceId));
    CHECK_ACL(aclrtCreateContext(&context, deviceId));
    aclrtStream stream = nullptr;
    CHECK_ACL(aclrtCreateStream(&stream));

    uint8_t *param1Host;
    uint8_t *param1Device;
    CHECK_ACL(aclrtMallocHost((void **)(&param1Host), param1FileSize));
    CHECK_ACL(aclrtMalloc((void **)&param1Device, param1FileSize, ACL_MEM_MALLOC_HUGE_FIRST));
    ReadFile("./input/x1_gm.bin", param1FileSize, param1Host, param1FileSize);
    CHECK_ACL(aclrtMemcpy(param1Device, param1FileSize, param1Host, param1FileSize, ACL_MEMCPY_HOST_TO_DEVICE));

    uint8_t *param2Host;
    uint8_t *param2Device;
    CHECK_ACL(aclrtMallocHost((void **)(&param2Host), param2FileSize));
    CHECK_ACL(aclrtMalloc((void **)&param2Device, param2FileSize, ACL_MEM_MALLOC_HUGE_FIRST));
    ReadFile("./input/x2_gm.bin", param2FileSize, param2Host, param2FileSize);
    CHECK_ACL(aclrtMemcpy(param2Device, param2FileSize, param2Host, param2FileSize, ACL_MEMCPY_HOST_TO_DEVICE));

    uint8_t *param3Host;
    uint8_t *param3Device;
    CHECK_ACL(aclrtMallocHost((void **)(&param3Host), param3FileSize));
    CHECK_ACL(aclrtMalloc((void **)&param3Device, param3FileSize, ACL_MEM_MALLOC_HUGE_FIRST));
    std::cout << "乘法开始\n";
    for (int i = 0; i < 5; i++)
    {
        CHECK_ACL(aclrtSynchronizeStream(stream));
        auto start = std::chrono::high_resolution_clock::now();
        // ACLRT_LAUNCH_KERNEL(matmul_custom)(
        //     blockDim, stream, param1Device, param2Device, param3Device,
        //     M, N, K,
        //     L1_m, L1_k, L1_n, L2_m, L2_k, L2_n, buffer_num);
        // matmul_custom_do(blockDim, nullptr, stream, param1Device, param2Device, param3Device,
        //                 M, N, K,
        //                 L1_m, L1_k, L1_n, L2_m, L2_k, L2_n, buffer_num);
        ACLRT_LAUNCH_KERNEL(matmul_custom)(
            blockDim, stream, param1Device, param2Device, param3Device, M, N, K);
        CHECK_ACL(aclrtSynchronizeStream(stream));
        auto end = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double> diff = (end - start) * 1000;
        std::cout << "第" << i << "轮乘法耗时为: " << diff.count() << " ms\n";
    }
    // system("echo '' >> result.txt");

    CHECK_ACL(aclrtSynchronizeStream(stream));

    printf("param3FileSize %zu \n", param3FileSize);
    CHECK_ACL(aclrtMemcpy(param3Host, param3FileSize, param3Device, param3FileSize, ACL_MEMCPY_DEVICE_TO_HOST));
    WriteFile("./output/output.bin", param3Host, param3FileSize);
    CHECK_ACL(aclrtFree(param3Device));
    CHECK_ACL(aclrtFreeHost(param3Host));

    CHECK_ACL(aclrtDestroyStream(stream));
    CHECK_ACL(aclrtDestroyContext(context));
    CHECK_ACL(aclrtResetDevice(deviceId));
    CHECK_ACL(aclFinalize());

    return 0;
}